-- LiteStats 0.9
------------------------------------------------------------------------------------
-- * Configure the modules below, if you need more control, edit the core modules.
-- * AutoSell and AutoRepair can be toggled on/off by right-clicking the text display.
-- * Junk exceptions for AutoSelling can be configured by the /junk command.
------------------------------------------------------------------------------------

-- Modules Config: Deleting any variable will likely cause errors.
local modules = {
	["Memory"] = {
		enabled = true, fmt = "%smB", -- "12.5mB"
		anchor_frame = "LChat", anchor_to = "left", anchor_from = "left",
		x_off = 40, y_off = 0,
		tip_anchor = "ANCHOR_BOTTOMLEFT", -- See http://www.wowwiki.com/API_GameTooltip_SetOwner for others.
		max_addons = 20, -- set to nil or comment/delete this line to disable 
	},
	["FPS"] = {
		enabled = true, fmt = "%sfps", -- "42fps"
		anchor_frame = "LChat", anchor_to = "center", anchor_from = "center",
		x_off = 0, y_off = 0,
	},
	["Latency"] = {
		enabled = true, fmt = "%sms", -- "77ms"
	 	anchor_frame = "LChat", anchor_to = "right", anchor_from = "right",
		x_off = -40, y_off = 0,
	},
	["Durability"] = {
		enabled = true, fmt = "%s%%D", -- "54%D" .. '%%' outputs '%'
		man = true, -- Hide bliz durability man
		gfunds = true, -- Change to false to disable guild repairing.
		anchor_frame = "RChat", anchor_to = "left", anchor_from = "left",
		x_off = 40, y_off = 0,
		tip_anchor = "ANCHOR_BOTTOMRIGHT"
	},
	["Gold"] = {
		enabled = true,
		style = 2, -- display styles: [1] 55g 21s 11c [2] 8829.4g [3] 823.55.94
		anchor_frame = "RChat", anchor_to = "center", anchor_from = "center",
		x_off = 0, y_off = 0,
		tip_anchor = "ANCHOR_BOTTOMRIGHT"
	},
	["Clock"] = {
		enabled = true,
		realmtime = false, -- set to true to display the realm time as the clock text
		anchor_frame = "RChat", anchor_to = "right", anchor_from = "right",
		x_off = -40, y_off = 0,
		tip_anchor = "ANCHOR_BOTTOMRIGHT"
	},
	["Ping"] = {
		enabled = true, fmt = "|cffff5555*|r %s |cffff5555*|r", -- "* Katae *"
		hide_self = false, -- Hide player ping
		anchor_frame = "Minimap", anchor_to = "bottom", anchor_from = "bottom",
		x_off = 0, y_off = 25,
	},
}

-- Font appearance conf
local s = { font = STANDARD_TEXT_FONT, color = {1,1,1}, size = 12, alpha = 0.8, outline = 1, shadow = {alpha=1,x=0} }

-- Tooltip text colors
local tthead = {r=0.4,g=0.78,b=1}
local ttsubh = {r=0.75,g=0.9,b=1}

------------------------------------------
-- Saved Vars Init
local sv, char, m = CreateFrame'frame', format("%s - %s", UnitName'player', GetRealmName())
sv:RegisterEvent'ADDON_LOADED'
sv:SetScript("OnEvent", function() LPSTAT = LPSTAT or {}; LPSTAT[char] = LPSTAT[char] or {} end)

------------------------------------------
local function formatgold(style, amount)
	local gold, silver, copper = floor(amount * .0001), floor(mod(amount * .01, 100)), floor(mod(amount, 100))
	if style == 1 then 
		return (gold > 0 and gold.."|cffffd700g|r " or "")
			.. (silver > 0 and silver.."|cffc7c7cfs|r " or "")
			.. ((copper > 0 or (gold == 0 and silver == 0)) and copper.."|cffeda55fc|r" or "")
	elseif style == 2 or not style then	
		return format("%.1f|cffffd700g|r", amount / 10000)
	elseif style == 3 then
		return format("|cffffd700%s|r.|cffc7c7cf%s|r.|cffeda55f%s|r", gold, silver, copper)
	end
end

local function formatmem(val)
	return format("%.1f "..(val > 1024 and "MiB" or "KiB"), val / (val > 1024 and 1024 or 1))
end

local function ColorGradient(perc, ...) -- function borrowed from SmoothDurability
	if perc >= 1 or perc <= 0 then
		return (perc >= 1 and select(select('#', ...) - 2, ...) or perc <= 0 and ...)
	end
	local segment, relperc = math.modf(perc*(select('#', ...)/3-1))
	local r1, g1, b1, r2, g2, b2 = select(segment*3+1, ...)
	return r1 + (r2-r1)*relperc, g1 + (g2-g1)*relperc, b1 + (b2-b1)*relperc
end

local function Coords()
	local x, y = GetPlayerMapPosition'player'
	if x == 0 or y == 0 then WorldMapFrame:Show(); WorldMapFrame:Hide(); x, y = GetPlayerMapPosition'player' end	
	return format(modules.Location.coord_fmt or "%d,%d", x*100, y*100)
end

local function HideTT() GameTooltip:Hide() end

------------------------------------------
--  Memory
m = modules.Memory; if m.enabled then lpanels:CreateLayout("Memory", {
	{	name = "Memory", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = {
			string = function(self)
				self.total = 0
				UpdateAddOnMemoryUsage()
				for i = 1, GetNumAddOns() do self.total = self.total + GetAddOnMemoryUsage(i) end
				if self.hover then self:GetParent().UpdateTip() end
				return format(modules.Memory.fmt, format("%.1f",self.total/1024))
			end, update = 5, font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow, 
		},
		OnLoad = function(self)
			self.UpdateTip = function()				
				GameTooltip:ClearLines()
				GameTooltip:AddDoubleLine("Addon Memory Usage:", formatmem(self.text.total),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
				GameTooltip:AddLine' '

				if modules.Memory.max_addons ~= 0 then
					if not self.timer or self.timer + 5 < time() then
						self.memlist, self.timer = {}, time()
						UpdateAddOnMemoryUsage()
						for i = 1, GetNumAddOns() do
							local addon, name = GetAddOnInfo(i)
							if IsAddOnLoaded(i) then tinsert(self.memlist, {name or addon, GetAddOnMemoryUsage(i)}) end
						end
						table.sort(self.memlist, function(a, b) return a[2] > b[2] end)				
					end
					local exmem = 0
					for i,t in ipairs(self.memlist) do
						if modules.Memory.max_addons and i > modules.Memory.max_addons then
							exmem = exmem + t[2]
						else GameTooltip:AddDoubleLine(t[1],formatmem(t[2]),1,1,1,1,1,1) end
					end
					if exmem > 0 then
						local more = #self.memlist - modules.Memory.max_addons
						GameTooltip:AddDoubleLine("+ "..more.." More...", formatmem(exmem),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
					end
					GameTooltip:AddDoubleLine(" ","--------------",1,1,1,0.5,0.5,0.5)
				end

				GameTooltip:AddDoubleLine("Default UI Memory Usage:", formatmem(gcinfo()-self.text.total),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
				GameTooltip:AddDoubleLine("Total Memory Usage:", formatmem(collectgarbage("count")),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
	            GameTooltip:Show()
			end
		end,
		OnEnter = function(self)
			GameTooltip:SetOwner(self, modules.Memory.tip_anchor)
			self.text.hover = true
			self.UpdateTip()
		end,
		OnLeave = function(self) self.text.hover = false; HideTT() end,
		OnClick = function(self, button)
			if button == "RightButton" then 
				UpdateAddOnMemoryUsage()
				local before = gcinfo()
				collectgarbage()
				UpdateAddOnMemoryUsage()
				print("|cff66C6FFGarbage collected:|r "..formatmem(before-gcinfo()))
				self.timer, self.text.elapsed = nil, 5
				self.UpdateTip()
			end
		end,
	}
}) end
------------------------------------------
--  FPS
m = modules.FPS; if m.enabled then lpanels:CreateLayout("FPS", {
	{	name = "FPS", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = {
			string = function() return format(modules.FPS.fmt, floor(GetFramerate())) end,
			font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow, 
		}
	}
}) end
------------------------------------------
--  Latency
m = modules.Latency; if m.enabled then lpanels:CreateLayout("Latency", {
	{	name = "Latency", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = {
			string = function() return format(modules.Latency.fmt, select(3,GetNetStats())) end,
			font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow, 
		}
	}
}) end
------------------------------------------
--  Durability
m = modules.Durability; if m.enabled then lpanels:CreateLayout("Durability", {
	{	name = "Durability", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = { font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow },
		OnLoad = function(self)
			CreateFrame("GameTooltip", "LPDURA")
			LPDURA:SetOwner(WorldFrame,"ANCHOR_NONE")			
			if modules.Durability.man then DurabilityFrame.Show = DurabilityFrame.Hide end
			self.slots = [[
				1:HEADSLOT
				3:SHOULDERSLOT
				5:CHESTSLOT
				6:WAISTSLOT
				7:LEGSSLOT
				8:FEETSLOT
				9:WRISTSLOT
				10:HANDSSLOT
				16:MAINHANDSLOT
				17:SECONDARYHANDSLOT
				18:RANGEDSLOT
			]]
			self:RegisterEvent'UPDATE_INVENTORY_DURABILITY'
			self:RegisterEvent'PLAYER_LOGIN'
			self:RegisterEvent'MERCHANT_SHOW'
			self.UpdateTip = function()
				GameTooltip:ClearLines()
				GameTooltip:AddLine("Durability Info",tthead.r,tthead.g,tthead.b)
				GameTooltip:AddLine' '
				local nodur, totalcost = true, 0
				for id, string in self.slots:gmatch("(%d-):(%w+)") do
					local dur, max = GetInventoryItemDurability(id)
					local string = getglobal(string)
					if dur ~= max then
						local perc = dur ~= 0 and floor(dur/max*100) or 0
						local r, g, b = ColorGradient(perc/100,1,0,0,1,1,0,0,1,0)
						local color = "|cff"..format("%02x%02x%02x", (r or 0)*255, (g or 0)*255, (b or 0)*255)
						GameTooltip:AddDoubleLine(string,format("|cffaaaaaa%s/%s | |r%s%s%%",dur,max,color,perc),1,1,1,1,1,1)
						totalcost = totalcost + select(3,LPDURA:SetInventoryItem("player",id))
						nodur = false
					end
				end
				if nodur then
					GameTooltip:AddLine("Good as new!",1,1,1)
				else
					GameTooltip:AddDoubleLine(" ","--------------",1,1,1,0.5,0.5,0.5)
					GameTooltip:AddDoubleLine("Repair Cost", formatgold(1, totalcost),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)	
				end
				GameTooltip:AddLine' '
				GameTooltip:AddDoubleLine(" ","AutoRepair: "..(LPSTAT[char].AutoRepair and "|cff55ff55ON" or "|cffff5555OFF"),1,1,1,ttsubh.r,ttsubh.g,ttsubh.b)
	            GameTooltip:Show()
			end
		end,
		OnEvent = function(self, event)
			if event == "UPDATE_INVENTORY_DURABILITY" or event == "PLAYER_LOGIN" then
				local durability = 100
				for id = 1, 18 do
			        local dur, max = GetInventoryItemDurability(id)
					if dur ~= max then
				        local perc = dur/max*100
				        if perc < durability then durability = floor(perc) end
					end
				end
				self.text:SetText(format(modules.Durability.fmt, durability))
			elseif event == "MERCHANT_SHOW" then
				if not LPSTAT[char].AutoRepair then LPSTAT[char].AutoRepair = false end
				if LPSTAT[char].AutoRepair and CanMerchantRepair() then
			        local cost, total = GetRepairAllCost(), 0
			        if cost > 0 then
						if gfunds and CanGuildBankRepair() then
							RepairAllItems(1)
							total = cost
						end
						if GetRepairAllCost() > 0 then
							for id = 1, 18 do
								local cost = select(3,LPDURA:SetInventoryItem("player",id))
								if cost ~= 0 and cost <= GetMoney() then
									if not InRepairMode() then ShowRepairCursor() end
									PickupInventoryItem(id)
									total = total + cost
								end
							end
							HideRepairCursor()
						end
						if total > 0 then print(format("|cff66C6FFRepair cost: |cffFFFFFF%s", formatgold(1, total))) end
					end
			    end
			end
		end,
		OnEnter = function(self)
			GameTooltip:SetOwner(self, modules.Durability.tip_anchor)
			self.UpdateTip()
		end,
		OnLeave = HideTT,
		OnClick = function(self, button)
			if button == "RightButton" then
				LPSTAT[char].AutoRepair = not LPSTAT[char].AutoRepair
				self.UpdateTip()
			end
		end
	}
}) end
------------------------------------------
--  Gold
m = modules.Gold; if m.enabled then lpanels:CreateLayout("Gold", {
	{	name = "Gold", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = { font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow },
		OnLoad = function(self)
			self.started = GetMoney()
			self:RegisterEvent'PLAYER_LOGIN'
			self:RegisterEvent'PLAYER_MONEY'
			self:RegisterEvent'MERCHANT_SHOW'
			if not LPSTAT.JunkIgnore then LPSTAT.JunkIgnore = {} end
			self.UpdateTip = function()
				local curgold = GetMoney()
				GameTooltip:ClearLines()
				GameTooltip:AddLine("Gold Info",tthead.r,tthead.g,tthead.b)
				GameTooltip:AddLine' '
				if self.started ~= curgold then
					local gained = curgold > self.started
					local color = gained and "|cff55ff55" or "|cffff5555"
					GameTooltip:AddDoubleLine("Session Gain/Loss", format("%s$|r %s %s$|r",color,formatgold(1, abs(self.started-curgold)),color),1,1,1,1,1,1)
					GameTooltip:AddLine' '
				end
				GameTooltip:AddLine("Server Gold",ttsubh.r,ttsubh.g,ttsubh.b)
				local total = 0
				for char, conf in pairs(LPSTAT) do
					local name, realm = strmatch(char, '(.+) %- (.+)')
					if realm == GetRealmName() then
						if conf.Gold then
							GameTooltip:AddDoubleLine(name, formatgold(1, conf.Gold),1,1,1,1,1,1)
							total = total + conf.Gold
						end
					end
				end
				GameTooltip:AddDoubleLine(" ","-----------------",1,1,1,0.5,0.5,0.5)
				GameTooltip:AddDoubleLine("Total", formatgold(1, total),ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
				GameTooltip:AddLine' '
				GameTooltip:AddDoubleLine(" ","AutoSell grays: "..(LPSTAT[char].AutoSell and "|cff55ff55ON" or "|cffff5555OFF"),1,1,1,ttsubh.r,ttsubh.g,ttsubh.b)
				GameTooltip:Show()
			end
		end,
		OnEvent = function(self, event)
			if event == "MERCHANT_SHOW" then
				if not LPSTAT[char].AutoSell then LPSTAT[char].AutoSell = true end
				if LPSTAT[char].AutoSell and not IsAltKeyDown() then
					local profit = 0
					for bag = 0, NUM_BAG_SLOTS do for slot = 0, GetContainerNumSlots(bag) do
						local link = GetContainerItemLink(bag, slot)
						if link then
							local itemstring, ignore = strmatch(link,"|Hitem:(%d-):"), false
							for _, exception in pairs(LPSTAT.JunkIgnore) do
								if exception == itemstring then ignore = true; break end
							end
							if select(3, GetItemInfo(link)) == 0 and not ignore then
								UseContainerItem(bag, slot)
								profit = profit + select(11, GetItemInfo(link)) * select(2, GetContainerItemInfo(bag, slot))
							end
						end
					end end
					if profit > 0 then print(format("|cff66C6FFJunk profit: |cffFFFFFF%s", formatgold(1, profit))) end
				end
				return
			end
			self.text:SetText(formatgold(modules.Gold.style, GetMoney()))
			LPSTAT[char].Gold = GetMoney()
		end,
		OnEnter = function(self)
			GameTooltip:SetOwner(self, modules.Gold.tip_anchor)
			self.UpdateTip()
		end,
		OnLeave = HideTT,
		OnClick = function(self, button)
			if button == "RightButton" then
				LPSTAT[char].AutoSell = not LPSTAT[char].AutoSell
				self.UpdateTip()
			end
		end
	}
})
------------------------------------------
--  /junk <add|rem(ove)|list|clear> [itemlink]
SLASH_KJUNK1, SlashCmdList.KJUNK = "/junk", function(s) 
	local action = strsplit(" ",s)
	if action == "list" then
		print("|cff66C6FFJunk exceptions:|r",(#LPSTAT.JunkIgnore == 0 and "None" or ""))
		for i, id in pairs(LPSTAT.JunkIgnore) do
			local link = select(2, GetItemInfo(id))
			print("- ["..i.."]",link)
		end
		return
	elseif action == "clear" then
		LPSTAT.JunkIgnore = {}
		print("|cff66C6FFCleared junk exceptions list.")
		return
	elseif action == "add" or strfind(action,"^del") or strfind(action,"^rem") then
		for id in s:gmatch("|Hitem:(%d-):") do
			local link = select(2, GetItemInfo(id))
			if action == "add" then
				if select(3, GetItemInfo(id)) == 0 then
					if not tContains(LPSTAT.JunkIgnore,id) then
						tinsert(LPSTAT.JunkIgnore,id)
						print('|cff66C6FFAdded junk exception:|r',link)
					else
						print(link,'|cff66C6FFis already in exceptions list.')
					end
				else print(link,'|cff66C6FFis not junk.') end
			elseif strfind(action,"^del") or strfind(action,"^rem") then
				tDeleteItem(LPSTAT.JunkIgnore,id)
				print('|cff66C6FFRemoved junk exception:|r',link)
			end
		end
	else
		print('|cffffffffLite|cff66C6FFStats|r: Junk List')
		print('/junk <add||rem(ove)> [itemlink] - Add/remove exception.')
		print('/junk list - List currently ignored items.')
		print('/junk clear - Clear exceptions list.')
	end
end end
------------------------------------------
--  Clock
m = modules.Clock; if m.enabled then lpanels:CreateLayout("Clock", {
	{	name = "Clock", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99, --height = 11,
		text = {
			string = function()
				if modules.Clock.realmtime then
					local hour, min, pm = GetGameTime()
					if hour > 12 then hour = hour - 12; pm = true elseif hour == 0 then hour = 12 end
					return hour..":"..format("%02.f",min)..(pm and "P" or "A")
				else
					return format("%01.f",date("%I"))..":"..date("%M")..strupper(strsub(date("%p"),0,1))
				end
			end, font = s.font, color = s.color, size = s.size, alpha = s.alpha, outline = s.outline, shadow = s.shadow, 
		},
		OnEnter = function(self)
			GameTooltip:SetOwner(self, modules.Clock.tip_anchor)
			GameTooltip:ClearLines()
			
			local hour, min, pm = GetGameTime()
			if hour > 12 then hour = hour - 12; pm = true elseif hour == 0 then hour = 12 end
			local rtime = hour..":"..format("%02.f",min)..(pm and "pm" or "am")
			local ltime = format("%01.f",date("%I"))..":"..date("%M")..strlower(date("%p"))
			
			local wgtime = GetWintergraspWaitTime() or nil
			if wgtime == nil then
				wgtime = "In Progress"
			else
				local hour = tonumber(format("%01.f", floor(wgtime/3600)))
				local min = format(hour>0 and "%02.f" or "%01.f", floor(wgtime/60 - (hour*60)))
				local sec = format("%02.f", floor(wgtime - hour*3600 - min *60))				
				wgtime = (hour>0 and hour..":" or "")..min..":"..sec
			end
			
			GameTooltip:AddLine(date("%A, %B %d"),tthead.r,tthead.g,tthead.b)
			GameTooltip:AddLine' '
			GameTooltip:AddDoubleLine("Local Time",ltime,ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
			GameTooltip:AddDoubleLine("Realm Time",rtime,ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
			GameTooltip:AddLine' '
			GameTooltip:AddDoubleLine("Time to Wintergrasp",wgtime,ttsubh.r,ttsubh.g,ttsubh.b,1,1,1)
			GameTooltip:Show()
		end,
		OnLeave = HideTT,
		OnClick = function(_,b) (b == "RightButton" and ToggleTimeManager or ToggleCalendar)() end
	}
}) end
------------------------------------------
--  Ping
m = modules.Ping; if m.enabled then lpanels:CreateLayout("Ping", {
	{	name = "Ping", anchor_frame = m.anchor_frame, anchor_to = m.anchor_to, anchor_from = m.anchor_from,
		x_off = m.x_off, y_off = m.y_off, strata = "HIGH", level = 99,
		text = { font = s.font, size = s.size, outline = s.outline, shadow = s.shadow },
		OnLoad = function(self) self:RegisterEvent'MINIMAP_PING' end,
		OnEvent = function(self, event, unit)
			if unit == "player" and modules.Ping.hide_self then return end
			if (unit == "player" and self.timer and time() - self.timer > 1) or not self.timer or unit ~= "player" then
				local class = (CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS)[select(2,UnitClass(unit))]
				self.text:SetText(format(modules.Ping.fmt, UnitName(unit)))
				self.text:SetTextColor(class.r,class.g,class.b,1)
	 			if UIFrameIsFading(self) then UIFrameFlashRemoveFrame(self) end
				UIFrameFlash(self, 0.2, 2.8, 8, false, 0, 5)
				self.timer = time()
			end
		end
	}
}) end
------------------------------------------
-- Applying modules
lpanels:ApplyLayout(nil,"Gold","FPS","Memory","Latency","Durability","Clock","Ping")
